package cn.zswltech.gruul.xxljob;

import cn.hutool.core.util.ObjectUtil;
import cn.zswltech.gruul.common.constant.RedisKeyConstant;
import cn.zswltech.gruul.common.constant.UserConstants;
import cn.zswltech.gruul.common.dal.dao.OrgDOMapper;
import cn.zswltech.gruul.common.dal.dao.RoleDOMapper;
import cn.zswltech.gruul.common.dal.dao.UserDOMapper;
import cn.zswltech.gruul.common.entity.OrgDO;
import cn.zswltech.gruul.common.entity.RoleDO;
import cn.zswltech.gruul.common.entity.UserDO;
import cn.zswltech.gruul.util.RedisLuaUtil;
import cn.zswltech.gruul.web.api.util.AccountUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.hikvision.aksk.entity.InterfaceData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @author Jim
 * @version 1.0.0
 * @descripition: 云狐信息同步
 * @date 2024/2/19 9:53
 */
@Component
@Slf4j
public class HttpYunHuInfoSync extends YunHuInfoSyncHandler{
    @Autowired
    private RedisLuaUtil redisLuaUtil;
    @Override
    public void userSyncer() {
        pullUserInfo();
    }

    @Override
    public void orgSyncer() {
       pullOrgInfo();
    }

    private static final String DEFAULT_ROLE_NAME = "无权限员工";
    private static final String pwd = UserConstants.DEFAULT_SECRET;
    private static final String DEFAULT_CREAT_BY = "同步";
    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private YunHuInfoQueue yunHuInfoQueue;

    @Autowired
    private UserDOMapper userDOMapper;

    @Autowired
    private OrgDOMapper orgDOMapper;

    @Autowired
    private RoleDOMapper roleDOMapper;

    /**
     * 获取云狐用户数据
     * @return
     */
    public void pullUserInfo(){
        // 云狐用户数据1W+ 一次最大拉取数据1W条  需要拉取两次
        for (int i=1;i<3;i++){
            JSONObject param = new JSONObject();
            param.put("page_no", String.valueOf(i));
            param.put("page_size", 10000);
            InterfaceData interfaceData = YunHuConnectUtil.buildInterfaceData(YunHuConstant.USER_URL, param.toJSONString());
            String response = null;
            try {
                response = YunHuConnectUtil.request(interfaceData);
            } catch (Exception e) {
                log.error("请求云湖用户数据失败",e);
                throw new RuntimeException("请求云湖用户数据失败"+e);
            }
            String result = parseResult(response);
            log.info("云湖用户原始数据：{}", result);
            List<YunHuUser> yunHuUsers = Optional.ofNullable(JSONObject.parseArray(result, YunHuUser.class)).orElse(Collections.emptyList());
            List<List<YunHuUser>> lists = Lists.partition(yunHuUsers, 200);
            lists.stream().forEach(item->{
                        yunHuInfoQueue.offerUser(item);
                        log.info("云湖用户数据入队，用户数：{}", yunHuUsers.size());
                    });
        }
    }



    /**
     * 获取云湖机构信息
     * @return
     */
    public void pullOrgInfo(){
        JSONObject param = new JSONObject();
        param.put("page_no", "1");
        param.put("page_size", "10000");
        InterfaceData interfaceData = YunHuConnectUtil.buildInterfaceData(YunHuConstant.ORG_URL, param.toJSONString());
        String response = null;
        try {
            response = YunHuConnectUtil.request(interfaceData);
        } catch (Exception e) {
            log.error("请求云湖机构数据失败", e);
            throw new RuntimeException("请求云湖用户数据失败"+e);
        }
        String result = parseResult(response);
        log.info("云湖机构原始数据：{}");
        List<YunHuOrg> yunHuOrgs = Optional.ofNullable(JSONObject.parseArray(result, YunHuOrg.class)).orElse(Collections.emptyList());
        List<List<YunHuOrg>> lists = Lists.partition(yunHuOrgs, 2);
        yunHuInfoQueue.offerOrg(yunHuOrgs);
        log.info("云湖机构数据入队，机构数：{}", yunHuOrgs.size());
//        lists.stream().forEach(item->{
//            yunHuInfoQueue.offerOrg(item);
//            log.info("云湖机构数据入队，机构数：{}", yunHuOrgs.size());
//        });
    }

    /**
     * 解析云湖响应
     * @param response 云狐响应
     * @return 需要的数据
     */
    private String parseResult(String response) {
        if (StringUtils.isEmpty(response)) {
            return null;
        }
        JSONObject parseObject = JSONObject.parseObject(response);
        String code = parseObject.getString("code");
        if (YunHuConstant.SUCCESS_CODE.equals(code)) {
            String data = parseObject.getString("data");
            return JSONObject.parseObject(data).getString("result");
        }
        return null;
    }

    /**
     * 获取待更新的数据
     *  1.新增数据
     *  2.更新时间更新 参照经分系统 只做新增不做删除和更新
     * @param list 待过滤数据
     */
    public List<YunHuUser> getNeedUpdateUsers(List<YunHuUser> list){
        Map<String, Date> newUserModifyMap = list.stream().collect(Collectors.toMap(YunHuUser::getEmpId, YunHuUser::getGmtModified));
        Set<String> empIds = newUserModifyMap.keySet().stream().collect(Collectors.toSet());
        RMap<String, String> map = redissonClient.getMap(RedisKeyConstant.YUNHU_USER_MODIFY_DATE_KEY);
        Map<String, String> oldUserModifyMap = map.getAll(empIds);
        List<String> needUpdateEmpIds = new ArrayList<>(list.size());
        for (String empId : empIds) {
            if (!oldUserModifyMap.containsKey(empId)){
                needUpdateEmpIds.add(empId);
            }

//            else {
//                String oldUpdateTime = oldUserModifyMap.get(empId);
//                Date newUpdateTime = newUserModifyMap.get(empId);
//                if (newUpdateTime.after(new Date(oldUpdateTime))){
//                    needUpdateEmpIds.add(empId);
//                }
//            }
        }
        if (ObjectUtil.isEmpty(needUpdateEmpIds)){
            return Collections.emptyList();
        }
        return list.stream().filter(item -> needUpdateEmpIds.contains(item.getEmpId())).collect(Collectors.toList());
    }

    /**
     * 获取待更新的数据
     *  1.新增数据
     *  2.更新时间更新 参照经分系统 只做新增不做删除和更新
     * @param list 待过滤数据
     */
    public List<YunHuOrg> getNeedUpdateOrgs(List<YunHuOrg> list){
        Map<String, Date> newOrgModifyMap = list.stream().collect(Collectors.toMap(YunHuOrg::getOrgId, YunHuOrg::getGmtModified));
        Set<String> orgIds = newOrgModifyMap.keySet().stream().collect(Collectors.toSet());
        RMap<String, String> map = redissonClient.getMap(RedisKeyConstant.YUNHU_USER_MODIFY_DATE_KEY);
        Map<String, String> oldOrgModifyMap = map.getAll(orgIds);
        List<String> needUpdateOrgIds = new ArrayList<>(list.size());
        for (String orgId: orgIds) {
            if (!oldOrgModifyMap.containsKey(orgId)){
                needUpdateOrgIds.add(orgId);
            }

//            else {
//                String oldUpdateTime = oldUserModifyMap.get(empId);
//                Date newUpdateTime = newUserModifyMap.get(empId);
//                if (newUpdateTime.after(new Date(oldUpdateTime))){
//                    needUpdateEmpIds.add(empId);
//                }
//            }
        }
        if (ObjectUtil.isEmpty(needUpdateOrgIds)){
            return Collections.emptyList();
        }
        return list.stream().filter(item->item.getOrgCode() !=null).filter(item->item.getSuperiorOrgId()!=null).filter(item -> needUpdateOrgIds.contains(item.getOrgId())).collect(Collectors.toList());
    }

    /**
     * 用户转换
     * @param needUpdateUsers 待更新用户
     * @return 转换后的用户
     */
    public List<UserDO> yunHuUserConvert(List<YunHuUser> needUpdateUsers) {
        List<UserDO> result = new ArrayList<>(needUpdateUsers.size());
        for (YunHuUser needUpdateUser : needUpdateUsers) {
            UserDO userDO = new UserDO();
            userDO.setAccount(needUpdateUser.getEmpId());
            UserDO selectOne = userDOMapper.selectOne(userDO);
            if (selectOne != null) {
                continue;
            }

            UserDO user = createUser(new Date(), needUpdateUser.getEmpId(), needUpdateUser.getEmpName(), pwd, new Date(2025, 0, 1));
            result.add(user);
        }
        return result;
    }

    private UserDO createUser(Date date, String empId, String empName, String pwd, Date expiration) {
        String salt = AccountUtil.genSalt();
        UserDO userDO = new UserDO();
        userDO.setGmtCreate(date);
        userDO.setGmtModified(date);
        userDO.setAccount(empId);
        userDO.setUserName(empName);
        userDO.setPwd(AccountUtil.genPwd(pwd, salt));
        userDO.setExpiration(expiration);
        userDO.setStatus(UserConstants.ACCOUNT_STATUS_DEFAULT);
        userDO.setCreateBy(DEFAULT_CREAT_BY);
        userDO.setSalt(salt);

        return userDO;
    }

    private Long getRoleUuid(Long orgId, String name) {
        RoleDO roleDO = new RoleDO();
        roleDO.setOrgId(orgId);
        roleDO.setName(name);
        RoleDO role = roleDOMapper.selectOne(roleDO);
        return role.getId();
    }

    /**
     * 机构转换
     * @param needUpdateOrgs 带转换机构
     * @return 权限表机构
     */
    public List<OrgDO> yunHuOrgConvert(List<YunHuOrg> needUpdateOrgs) {
        List<OrgDO> orgDoList = new ArrayList<>(needUpdateOrgs.size());
        Map<String, String>  orgCode2ParentIdMap = needUpdateOrgs.stream().collect(Collectors.toMap(YunHuOrg::getOrgCode, YunHuOrg::getSuperiorOrgId));
        Map<String, String>  orgId2CodeMap = needUpdateOrgs.stream().collect(Collectors.toMap(YunHuOrg::getOrgId, YunHuOrg::getOrgCode));
        Map<String,String> orgCode2ParentCodeMap = new HashMap<>();
        for (Map.Entry<String, String> entry : orgCode2ParentIdMap.entrySet()) {
            String parentId = entry.getValue();
            if (orgId2CodeMap.containsKey(parentId)){
                orgCode2ParentCodeMap.put(entry.getKey(), orgId2CodeMap.get(parentId));
            }
        }
        for (YunHuOrg needUpdateOrg : needUpdateOrgs) {
            OrgDO orgDO = toOrgDo(needUpdateOrg,orgCode2ParentCodeMap);
            if (orgDO != null){
                orgDoList.add(orgDO);
            }
        }
        if (ObjectUtil.isNotEmpty(orgDoList)){
            Map<String, Long> code2IdMap = orgDoList.stream().collect(Collectors.toMap(OrgDO::getCode, OrgDO::getId));
            for (OrgDO orgDO : orgDoList) {
                if (orgDO.getParentCode()!=null){
                    orgDO.setParentId(code2IdMap.get(orgDO.getParentCode()));
                }
            }
            // 层级
            List<OrgDO> rootOrgDos = orgDoList.stream().filter(item -> item.getParentCode() == null).collect(Collectors.toList());
            Map<String, List<OrgDO>> parentCodeOrgGroup = orgDoList.stream().filter(item -> item.getParentCode() != null).collect(Collectors.groupingBy(OrgDO::getParentCode));
            for (OrgDO rootOrgDo : rootOrgDos) {
                OrgDO parentOrgDo = rootOrgDo;
                calLevel(parentOrgDo,parentCodeOrgGroup);
            }
        }
        return orgDoList;
    }

    private void calLevel(OrgDO parentOrgDo, Map<String, List<OrgDO>> parentCodeOrgGroup) {
        log.info("计算机构：{}的下级机构,当前机构层级;{}", parentOrgDo.getCode(),parentOrgDo.getLevel());
        if (!parentCodeOrgGroup.containsKey(parentOrgDo.getCode())){
            log.info("机构:{}没有下级机构了,停止递归", parentOrgDo.getFullName());
            return;
        }
        for (OrgDO child : parentCodeOrgGroup.get(parentOrgDo.getCode())) {
            child.setLevel(parentOrgDo.getLevel()+1);
            calLevel(child, parentCodeOrgGroup);
        }
    }

    /**
     * 机构转换
     * @param yunHuOrg 云湖机构
     * @return 权限表机构
     */
    private OrgDO toOrgDo(YunHuOrg yunHuOrg,Map<String,String> orgCode2ParentCodeMap) {
        String parentCode = orgCode2ParentCodeMap.get(yunHuOrg.getOrgCode());
        Date date = new Date();
        // 有上层机构
        if (parentCode != null){
            OrgDO orgDO = new OrgDO();
            orgDO.setId(redisLuaUtil.getTableId(RedisKeyConstant.ORG_TABLE_NAME));
            orgDO.setGmtCreate(date);
            orgDO.setParentCode(parentCode);
            orgDO.setGmtModified(date);
            orgDO.setType(Integer.valueOf(yunHuOrg.getOrgTypeCode().replace("0","")));
            orgDO.setCode(yunHuOrg.getOrgCode());
            orgDO.setName(yunHuOrg.getFullName());
            orgDO.setCreateBy(DEFAULT_CREAT_BY);
            return orgDO;
        }
        //TODO 根节点机构
        if (parentCode == null && yunHuOrg.getSuperiorOrgId().equals("0")){
            OrgDO orgDO = new OrgDO();
            orgDO.setId(redisLuaUtil.getTableId(RedisKeyConstant.ORG_TABLE_NAME));
            orgDO.setGmtCreate(date);
            orgDO.setGmtModified(date);
            orgDO.setType(Integer.valueOf(yunHuOrg.getOrgTypeCode().replace("0","")));
            orgDO.setCode(yunHuOrg.getOrgCode());
            orgDO.setLevel(1);
            orgDO.setName(yunHuOrg.getFullName());
            orgDO.setCreateBy(DEFAULT_CREAT_BY);
            return orgDO;
        }
        return null;
    }
}
